home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / dviware / dvitovdu / unix / c / dvireader.h < prev    next >
Text File  |  1990-10-01  |  20KB  |  408 lines

  1. /* Original Author:         Andrew Trevorrow
  2.    Implementation: Modula-2 under VAX/UNIX 4.2 BSD
  3.    Date Started:   June, 1986
  4.  
  5.    Description:
  6.    DVIReader exports routines and data structures for moving about randomly
  7.    in a TeX82 DVI file and interpreting pages.
  8.    DVItoVDU (an interactive page previewer) is currently the only client,
  9.    but it is anticipated that DVIReader could just as well form the basis of a
  10.    more conventional DVI translator (such as a non-interactive device driver).
  11.  
  12.    Limitations:
  13.    - DVIReader does not look at the preamble and so ignores any comments there.
  14.    - DVIReader does not do any terminal i/o, even upon detecting a fatal error.
  15.      The client must write a DVIErrorRoutine that will be invoked at the time
  16.      an error is detected.  See below for details.
  17.    - DVIReader knows little about the format of PXL, RST or similar such files.
  18.      It only knows they contain crucial information for typesetting a DVI file.
  19.      The client must write a PixelTableRoutine to read some sort of font file
  20.      and fill in the pixel table information used to interpret a DVI page.
  21.      See below for details.
  22.    - The data structures used to represent an interpreted DVI page are best
  23.      suited to a client whose output device is randomly addressable.
  24.      Some clients may need to convert the information in the data structures
  25.      into a more suitable format (such a task may even be impractical).
  26.  
  27.    Algorithm for a simple DVI translator:
  28.       < initialize the DVIErrorRoutine used to handle various errors >
  29.       < initialize filespec, resolution, etc. >
  30.       OpenDVIFile(filespec);
  31.       < initialize magnification, probably with DVImag >
  32.       SetConversionFactor(resolution,magnification);
  33.       < initialize the SpecialRoutine used in InterpretPage >
  34.       < initialize the PixelTableRoutine used in InterpretPage >
  35.       FOR p := 1 TO totalpages DO
  36.          MoveToDVIPage(p);
  37.          InterpretPage;
  38.          IF pageempty THEN
  39.             < process an empty page >
  40.          ELSE
  41.             < check that the page edges are within the paper edges >
  42.             < process the rule list >
  43.             < process the character list for each font used on the page >
  44.          END;
  45.       END;
  46.       CloseDVIFile;
  47.  
  48. -------------------------------------------------------------------------------
  49.    This version converted to C and ported to BSD and System V UNIX by
  50.    some chaps at Kernel Technology up to September 1989.  Contact
  51.    mjh@uk.co.kernel (Mark J. Hewitt) with bug fixes etc.
  52.  
  53.    Involved were:    Mark J. Hewitt
  54.                Dave Dixon
  55.             Marc Hadley
  56. */
  57.  
  58. static char *sccsid_dvir[] = "@(#)dvireader.h    1.1";
  59.  
  60. #define   RULETABLESIZE  300     /* maximum number of rules in a ruletable   */
  61. #define   CHARTABLESIZE  3000    /* maximum number of chars in a chartable   */
  62. #define   MAXFONTSPEC    82      /* maximum length of a font file spec       */
  63. #define   MAXTEXCHAR     129     /* DVI and font files should use char codes */
  64.                                  /* in 0..127 */
  65.                                  /* (Knuth's TRIP.DVI has codes > 127!)     */
  66.  
  67.    /* The major page structures are defined first.
  68.       Information about the rules and characters appearing on a page is stored
  69.       in dynamic one-way lists to avoid imposing any limit on their numbers.
  70.       To reduce pointer overheads, the nodes in these lists contain large
  71.       tables (the values of RULETABLESIZE and CHARTABLESIZE have been chosen
  72.       so that the vast majority of DVI pages will only require one-node lists).
  73.       When interpreting a DVI page, DVIReader adds a new rule or character node
  74.       to the TAIL of the relevant list.  This is done so that when the client
  75.       accesses such lists (starting at the head), rules and characters will be
  76.       processed in somewhat the same sequence as seen in the DVI file; i.e.,
  77.       top-to-bottom and left-to-right across the page.
  78.       Since a character list is part of the information stored for a font,
  79.       the precise sequence in which DVI characters are seen is not remembered.
  80.       Font information is also linked together in a one-way list, but the
  81.       ordering is more or less random (see, however, the SortFonts routine).
  82.    */
  83.  
  84.    struct  ruleinfo {                     /* a node in a list of ruletables  */
  85.            unsigned int rulecount ;       /* number of rules in ruletable    */
  86.            struct ruletab {
  87.                   int hp, vp ;            /* pixel coords of rule's ref point*/
  88.                   int wd, ht ;            /* dimensions of rule in pixels    */
  89.            } ruletable[RULETABLESIZE];
  90.            struct ruleinfo  *nextrule ;   /* next node in rule list          */
  91.    } ;
  92.  
  93.    typedef struct  ruleinfo  *ruleinfoptr ;
  94.  
  95.    struct  charinfo {                     /* a node in list of chartables    */
  96.            unsigned int charcount ;       /* number of chars in chartable    */
  97.            struct chartab {
  98.                  int    hp, vp ;          /* pixel coords of char's ref point*/
  99.                  short  code;             /* char's code and pixeltable index*/
  100.            } chartable[CHARTABLESIZE];
  101.            struct charinfo  *nextchar ;   /* next node in char list          */
  102.    } ;
  103.  
  104.    typedef struct  charinfo  *charinfoptr ;
  105.  
  106.    /* pixeltable must be filled in by the client's PixelTableRoutine.
  107.       DVIReader uses wd, ht, xo and yo to calculate minhp, minvp, maxhp and
  108.       maxvp.  It uses dwidth and pwidth to advance horizontally after
  109.       setting a character.  The mapadr field is not used by DVIReader.
  110.    */
  111.       typedef struct pixtabstr {
  112.          int  wd, ht ;    /* glyph width and height in pixels; they
  113.                                  define the size of the smallest box
  114.                                  containing all the black pixels             */
  115.          int  xo, yo ;    /* x and y offsets from top left corner
  116.                                  of glyph to character's reference point     */
  117.          int  dwidth ;    /* advance width in DVI units computed from
  118.                                  fix width stored in font file               */
  119.          int  pwidth ;    /* advance width in pixels computed from
  120.                                  fix width stored in font file               */
  121.          unsigned int mapadr ;   /* starting address of pixel map in font file
  122.                                  (could be a word or byte offset; DVIReader
  123.                                  neither knows nor cares)                    */
  124.       } pixtabstr;
  125.  
  126.    typedef struct pixtabstr *pixeltableptr ;
  127.  
  128.    typedef char  fontstring[MAXFONTSPEC] ;
  129.  
  130.    typedef struct    fontinfo   *fontinfoptr;
  131.  
  132.       struct  fontinfo     {            /* a node in list of fonts           */
  133.               short fontused;           /* is font used on current page?     */
  134.               int   fontnum;            /* DVI font number: -2^31 .. 2^30 - 1*/
  135.               unsigned int  scaledsize; /* scaled font size in DVI units     */
  136.               unsigned int  designsize; /* design size in DVI units          */
  137.               fontstring    fontarea;   /* explicit font directory           */
  138.               unsigned int  fontarealen;/* length of fontarea                */
  139.               fontstring    fontname;   /* font name; e.g., "cmr10"          */
  140.               unsigned int  fontnamelen;/* length of font name               */
  141.               fontstring    fontspec;   /* client's font file specification  */
  142.               unsigned int  fontspeclen;/* length of fontspec                */
  143.               unsigned int  totalchars; /* number of chars from font on page */
  144.               charinfoptr   charlist;   /* head of char information list     */
  145.               charinfoptr   chartail;   /* tail of char information list     */
  146.               pixeltableptr pixelptr;   /* allocated once: 1st time font used*/
  147.               fontinfoptr   nextfont;   /* next node in font list            */
  148.       };
  149.  
  150.    /* For the parameter in MoveToTeXPage: */
  151.    typedef   int  TeXcounters[10];
  152.  
  153.       struct TeXpageinfo {
  154.              TeXcounters    value ;           /* \count0..\count9 values    */
  155.              short          present[10] ;      /* is counter relevant?      */
  156.              short          lastvalue ;       /* last relevant counter      */
  157.       };
  158.  
  159.    /* For the parameter in client's DVIErrorRoutine: */
  160.  
  161. typedef unsigned short DVIerrorcodes;
  162.  
  163. #define DVIunopened      0x00  /* OpenDVIFile could not open the given file  */
  164. #define DVIempty         0x01  /* OpenDVIFile detected an empty file         */
  165. #define DVIbadid         0x02  /* OpenDVIFile found an invalid TeX82 DVI file*/
  166. #define DVIstackoverflow 0x03  /* OpenDVIFile found DVIReader's stck too smll*/
  167. #define DVIbadchar       0x04  /* InterpretPage is ignoring a */
  168.                                /* char code > MAXTEXCHAR */
  169.                                /* (found while processing currfont^)*/
  170. #define DVIcatastrophe   0x05  /* DVIReader found a situation that should */
  171.                                /* never occur; client should scream */
  172.                                /* for help and halt*/
  173.  
  174.    /* For the function parameter in client's SpecialRoutine: */
  175. typedef  int (*GetByteFunction)() ;   /* returns next DVI byte       */
  176.  
  177.    /* Most of these should be treated as read-only parameters:               */
  178. unsigned int
  179.    DVImag,                        /* magnification stored in DVI file        */
  180.    totalpages,                    /* number of pages in DVI file             */
  181.    totalfonts,                    /* number of fonts in DVI file             */
  182.    currDVIpage;                   /* updated by MoveTo... calls              */
  183.  
  184. TeXcounters
  185.    currTeXpage;                   /* ditto                                   */
  186.  
  187. unsigned int
  188.    totalrules;                    /* number of rules on current page         */
  189.  
  190. ruleinfoptr
  191.     rulelist,                     /* head of rule information list           */
  192.     ruletail;                     /* tail of rule information list           */
  193.  
  194. fontinfoptr
  195.     fontlist,                    /* head of font information list           */
  196.     currfont;                    /* InterpretPage's current font info       */
  197.  
  198. short
  199.    pageempty;                    /* is page empty of rules and chars?       */
  200.  
  201. int
  202.    minhp,                        /* minimum horizontal pixel coordinate     */
  203.    minvp,                         /* minimum vertical pixel coordinate       */
  204.    maxhp,                         /* maximum horizontal pixel coordinate     */
  205.    maxvp;                         /* maximum vertical pixel coordinate       */
  206.  
  207. void InitReader();
  208.  
  209. Void (*DVIErrorRoutine)();
  210.    /* The client MUST assign a procedure before the first OpenDVIFile call.
  211.       Various DVIReader routines will call this procedure if they detect some
  212.       sort of problem; the given argument will be one of the error codes
  213.       described above.
  214.       The client's routine can use this code to see what sort of error
  215.       has occurred and take appropriate action.  Most errors detected by
  216.       DVIReader are fatal; the client should print some sort of message
  217.       and halt.  See DVItoVDU for an example DVIErrorRoutine.
  218.    */
  219.  
  220. Void (*SpecialRoutine)();
  221.    /* The client can assign a procedure before the first InterpretPage call.
  222.       InterpretPage will call this procedure to process the bytes belonging to
  223.       a \special command.  The first argument gives the number of bytes; the
  224.       second argument is a function that returns the value of the next byte
  225.       (0..255, but usually the ordinal value of a displayable ASCII character).
  226.       The client's routine might look something like:
  227.           PROCEDURE MySpecialRoutine (totalbytes : INTEGER;
  228.                                       NextByte   : GetByteFunction);
  229.           VAR i, nextval : INTEGER;
  230.           BEGIN
  231.           FOR i := 1 TO totalbytes DO
  232.              nextval := NextByte();
  233.              < process nextval >
  234.           END;
  235.           END MySpecialRoutine;
  236.       If the client does not supply a SpecialRoutine, DVIReader will simply
  237.       ignore any \special bytes.
  238.    */
  239.  
  240. Void (*PixelTableRoutine)();
  241.    /* The client MUST assign a procedure before the first InterpretPage call.
  242.       InterpretPage will call this procedure immediately after allocating a
  243.       pixel table for currfont^.  This will only occur once per font (the
  244.       very first time the font is used).
  245.       DVIReader only knows about DVI files; the task of the PixelTableRoutine is
  246.       to fill in the current font's pixel table by reading the fontspec file.
  247.       (The fontspec string must first be built using the fontarea and fontname.)
  248.       This file could be a PXL file, an RST file, or some other type of file.
  249.       See DVItoVDU for an example of a PixelTableRoutine that reads a PXL file.
  250.    */
  251.  
  252.  
  253. /*PROCEDURE OpenDVIFile (filespec : ARRAY OF CHAR);*/
  254.  
  255. /* This must be the first DVIReader routine called.  If the given filespec can
  256.    be opened (and is a valid TeX82 DVI file) then the following global
  257.    variables are initialized:
  258.       DVImag      := magnification value stored in DVI file (TeX's \mag)
  259.       totalpages  := total number of pages in DVI file
  260.       currDVIpage := 0      (and remains so until a page is selected)
  261.       currTeXpage := ten 0s (ditto)
  262.       totalfonts  := total number of fonts in DVI file (= nodes in font list)
  263.       fontlist^.  (nodes are added to head of list)
  264.          fontused   := FALSE
  265.          fontnum    := internal DVI font number
  266.          scaledsize := scaled size of font (in DVI units)
  267.          designsize := design size of font (in DVI units)
  268.          fontarea   := a string of min(fontarealen,MAXFONTSPEC) characters
  269.          fontname   := a string of min(fontnamelen,MAXFONTSPEC) characters
  270.          fontspec   := a null string (fontspeclen := 0)
  271.          totalchars := 0
  272.          charlist   := NULL
  273.          chartail   := NULL
  274.          pixelptr   := NULL
  275.          nextfont   := next node in font list (if not NULL)
  276. */
  277.  
  278. /*PROCEDURE SetConversionFactor (resolution, magnification : CARDINAL);*/
  279.  
  280. /* This routine must be called before the first InterpretPage call.
  281.    DVIReader needs to know the client's resolution and magnification values
  282.    before it attempts to convert DVI dimensions into pixel values.
  283. */
  284.  
  285. /*PROCEDURE MoveToDVIPage  (n : CARDINAL);*/
  286. /*PROCEDURE MoveToNextPage (ascending : BOOLEAN);*/
  287. /*PROCEDURE MoveToTeXPage  (VAR newTeXpage : TeXpageinfo) : BOOLEAN;*/
  288.  
  289. /* Before calling InterpretPage, the client must position DVIReader to the
  290.    desired page by calling one of these MoveTo... routines.
  291.  
  292.    MoveToDVIPage will select the nth page in the DVI file; nothing will
  293.    happen if n is not in 1..totalpages.
  294.  
  295.    MoveToNextPage will select the next page, depending on the current page
  296.    and the specified direction.  If the value of currDVIpage is 0 (set in
  297.    OpenDVIFile), then MoveToNextPage will select the first page if ascending is
  298.    TRUE and the last page if ascending is FALSE.  If currDVIpage is > 0 then
  299.    MoveToNextPage will select currDVIpage+1 if ascending (unless currDVIpage =
  300.    totalpages, in which case it does nothing), or currDVIpage-1 if descending
  301.    (unless currDVIpage = 0).
  302.  
  303.    MoveToTeXPage will search for the lowest DVI page matching the given TeX page
  304.    specification.  (TeX stores the values of \count0,\count1,...,\count9 with
  305.    every DVI page.  Plain TeX uses \count0 to control page numbering.)
  306.    newTeXpage is a VAR parameter only for efficiency; it won't be changed.
  307.    The value array stores the requested counter values, the present array
  308.    indicates which counters are relevant and lastvalue indicates
  309.    the position (0..9) of the last relevant counter.
  310.    The client will probably need to first convert a more friendly representation
  311.    of a TeX page request into the TeXpageinfo format.  For example,
  312.    [2..5] would be converted to:         and [] would be converted to:
  313.    value     = [2,?,5,?,?,?,?,?,?,?]     value     = [?,?,?,?,?,?,?,?,?,?]
  314.    present   = [T,F,T,?,?,?,?,?,?,?]     present   = [F,?,?,?,?,?,?,?,?,?]
  315.    lastvalue =      2                    lastvalue =  0
  316.    MoveToTeXPage returns TRUE iff the requested TeX page is located.
  317.  
  318.    The global variables updated if a page is located by any MoveTo... call are:
  319.       currDVIpage := the current DVI page (1..totalpages)
  320.       currTeXpage := the ten TeX counter values stored with this page
  321.    Note that currDVIpage is initially 0 until one of these routines succeeds.
  322. */
  323.  
  324. /*PROCEDURE PixelRound (DVIunits : INTEGER) : INTEGER;*/
  325.  
  326. /* One of the important tasks the client's PixelTableRoutine must carry out
  327.    is to convert the fix width values from a fontspec file into DVI and pixel
  328.    units; i.e., the dwidth and pwidth values stored in the pixel table.
  329.    Once dwidth has been calculated (see DVITYPE or DVItoVDU for how to do this)
  330.    then pwidth is easy: pwidth := PixelRound(dwidth).
  331.    PixelRound can be used to convert any DVI dimension (+ve or -ve) into pixels.
  332. */
  333.  
  334. /*PROCEDURE InterpretPage;*/
  335.  
  336. /* This routine will interpret the current DVI page and update the major
  337.    data structures:
  338.       totalrules := number of rules on page
  339.       rulelist^. (nodes are added to tail of rule list)
  340.          rulecount  := number of rules in this ruletable
  341.          ruletable[0..rulecount-1].
  342.             hp, vp  := reference point of a rule
  343.             wd, ht  := pixel dimensions of a rule (both > 0)
  344.          nextrule   := next node in rule list (if not NULL)
  345.       ruletail   := pointer to last node in rule list
  346.  
  347.       fontlist^.
  348.          (the following fontinfo is relevant only if fontused is TRUE)
  349.          totalchars := number of chars on page from this font
  350.          charlist^. (nodes are added to tail of char list)
  351.             charcount  := number of chars in this chartable
  352.             chartable[0..charcount-1].
  353.                hp, vp  := reference point of a character
  354.                code    := TeX character code (and index into pixel table)
  355.             nextchar   := next node in char list (if not NULL)
  356.          chartail   := pointer to last node in char list
  357.          pixelptr^[0..maxTeXchar].
  358.             (filled in by client's PixelTableRoutine)
  359.             wd, ht  := glyph width and height in pixels
  360.             xo, yo  := offsets from the character's reference point
  361.             dwidth  := advance width in DVI units
  362.             pwidth  := advance width in pixels
  363.             mapadr  := starting address in fontspec of the glyph's pixel map
  364.          nextfont   := next node in font list (if not NULL)
  365.  
  366.       pageempty  := TRUE iff the page has no rules and no characters
  367.       minhp, minvp, maxhp, maxvp
  368.                  := the edges of the page (undefined if pageempty is TRUE)
  369.                     They define the smallest rectangle containing all
  370.                     black pixels AND all reference points on the page;
  371.                     (minhp,minvp) is the top left corner.
  372.  
  373.    Reference points for rules and characters are stored as a pair of
  374.    horizontal and vertical pixel coordinates.  The point (0,0) is assumed
  375.    to be the pixel 1 inch in from the top and left edges of an imaginary sheet
  376.    of paper.  Horizontal coordinates increase to the right and vertical
  377.    coordinates increase down the paper.
  378.    The number of pixels per inch is defined by the resolution parameter
  379.    given to SetConversionFactor.
  380. */
  381.  
  382. /*PROCEDURE SortFonts (VAR unusedlist : fontinfoptr);*/
  383.  
  384. /* This routine will sort fontlist in ascending order of totalchars.
  385.    The client may wish to do this after interpreting a page so that fonts
  386.    with the least number of characters on the page will be processed first.
  387.    The routine will also move all unused fonts to the end of fontlist so that
  388.    the client need only process fonts up to (but excluding) unusedlist
  389.    and not have to worry about checking the fontused flag.
  390.    For example:
  391.        SortFont(unusedlist);
  392.        thisfont := fontlist;
  393.        WHILE thisfont <> unusedlist DO
  394.           < process the font information in thisfont^ >
  395.           thisfont := thisfont^.nextfont;
  396.        END;
  397.    If unusedlist is NULL then either 1) all fonts are used on the current page
  398.    or 2) fontlist is also NULL (totalfonts = 0).
  399. */
  400.  
  401. /*PROCEDURE CloseDVIFile;*/
  402.  
  403. /* This routine closes the currently open DVI file; it is only mandatory if
  404.    OpenDVIFile is going to be called again.
  405.    All dynamic data structures are deallocated.
  406. */
  407.  
  408.